/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
 * secGear is licensed under the Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *     http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
 * PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include <stdio.h>
#include <unistd.h>
#include <linux/limits.h>
#include "enclave.h"
#include "helloworld_u.h"
#include "string.h"

#define BUF_LEN 32

struct ListNode{
    uint8_t hint;
    uint8_t key[32];
    uint8_t val[32];
    ListNode *nextPoint;
};

void printInfo(uint8_t* data){
    for (int i = 0; i < 32; ++i) {
        printf("%c", data[i]);
    }
}

int main()
{
    int  retval = 0;
    char *path = PATH;
    char buf[BUF_LEN];
    cc_enclave_t context = {};
    cc_enclave_result_t res = CC_FAIL;

    char real_p[PATH_MAX];
    /* check file exists, if not exist then use absolute path */
    if (realpath(path, real_p) == NULL) {
        if (getcwd(real_p, sizeof(real_p)) == NULL) {
            printf("Cannot find enclave.sign.so");
            // goto end;
            return res;
        }
        if (PATH_MAX - strlen(real_p) <= strlen("/enclave.signed.so")) {
            printf("Failed to strcat enclave.sign.so path");
            // goto end;
            return res;
        }
        (void)strcat(real_p, "/enclave.signed.so");
    }

    res = cc_enclave_create(real_p, AUTO_ENCLAVE_TYPE, 0, SECGEAR_DEBUG_FLAG, NULL, 0, &context);
    if (res != CC_SUCCESS) {
        printf("host create enclave error\n");
        // goto end; 
        return res;
    }
    printf("host create enclave success\n");

    res = get_string(&context, &retval, buf);
    if (res != CC_SUCCESS || retval != (int)CC_SUCCESS) {
        printf("Ecall enclave error\n");
    } else {
        printf("enclave say:%s\n", buf);
    }

    /////////////////////////
     ListNode head;
    head.hint = '\0'; // 初始化头节点
    ListNode searchList;
    searchList.hint = '\0';
    uint64_t head_addr = (uint64_t)&head;
    uint64_t searchList_addr = (uint64_t)&searchList;

    char choice;
    while(true){
        printf("请您选择您需要的功能：\n");
        printf("1. 存储\n");
        printf("2. 取值\n");
        printf("3. 退出\n");
        scanf("%c",&choice);
        if(choice == '1'){
            printf("请输入您要存储数据的键：");
            char input_key[33];
            scanf("%s",input_key);
            if(strlen(input_key) > 32){
                input_key[32] = '\0';
            }
            for(int i = strlen(input_key); i < 32; i++){
                input_key[i] = ' ';
            }
            input_key[32] = '\0';
            printf("请输入您要存储数据的值：");
            char input_val[33];
            scanf("%s",input_val);
            if(strlen(input_val) > 32){
                input_val[32] = '\0';
            }
            for(int i = strlen(input_val); i < 32; i++){
                input_val[i] = ' ';
            }
            input_val[32] = '\0';
            int res = setDataInEnclave(&context, &retval,head_addr,reinterpret_cast<uint8_t*>(input_key),reinterpret_cast<uint8_t*>(input_val));
            if(res == 0){
                printf("数据存储成功！\n");
            }
            else{
                printf("数据存储失败！\n");
            }
        }
        else if(choice == '2'){
            printf("请输入您要查找数据的键：");
            char input_key[33];
            scanf("%s",input_key);
            if(strlen(input_key) > 32){
                input_key[32] = '\0';
            }
            for(int i = strlen(input_key); i < 32; i++){
                input_key[i] = ' ';
            }
            input_key[32] = '\0';
            uint8_t val_rec[32] = {0};
            int res2 = getDataInEnclave(&context, &retval,head_addr,reinterpret_cast<uint8_t*>(input_key),searchList_addr,val_rec);
            if(res2 == 0){
                printf("数据查找成功！");
                printf("您查找的值为:\n");
                printf("============================\n");
                for (int i = 0; i < 32; ++i) {
                    printf("%c", val_rec[i]);
                }
                printf("\n============================\n");
                printf("\n");
            }
            else{
                printf("数据查找失败！\n");
            }
        }
        else if(choice == '3'){
            printf("程序已退出！\n");
            break;
        }
        else{
            printf("选项不存在，请重新输入！\n");
        }
        printf("\n");
        while(getchar() != '\n');
    }

    
    // uint8_t val_rec2[32] = {0};

    // setDataInEnclave(&context, &retval,head_addr,(uint8_t*)"abcdefghijklmnopqrstuvwxyz123456",(uint8_t*)"123456abcdefghijklmnopqrstuvwxyz");
    // setDataInEnclave(&context, &retval,head_addr,(uint8_t*)"oaugdfiugsoidfugwefiuwgfiougdsiu",(uint8_t*)"idzugfiubseifglwiuegfiuwgefowiug");
    // // std::cout << "First bit of hash value: " << static_cast<unsigned int>(head.hint) << std::endl;
    // getDataInEnclave(&context, &retval,head_addr,(uint8_t*)"abcdefghijklmnopqrstuvwxyz123456",searchList_addr,val_rec);
    // getDataInEnclave(&context, &retval,head_addr,(uint8_t*)"oaugdfiugsoidfugwefiuwgfiougdsiu",searchList_addr,val_rec2);
    // printf("search value1 is:\n");
    // for (int i = 0; i < 32; ++i) {
    //     printf("%c", val_rec[i]);
    // }
    // printf("\n");
    // printf("search value2 is:\n");
    // for (int i = 0; i < 32; ++i) {
    //     printf("%c", val_rec2[i]);
    // }
    // printf("\n");
    /////////////////////////

    res = cc_enclave_destroy(&context);
    if(res != CC_SUCCESS) {
        printf("host destroy enclave error\n");
    } else {
        printf("host destroy enclave success\n");
    }
// end:
//     return res;
}
